1
2
3
4
5
6
7
8
9
10
11
12
13 package org.apache.tapestry5.internal.services.assets;
14
15 import org.apache.tapestry5.internal.services.ResourceStreamer;
16 import org.apache.tapestry5.ioc.IOOperation;
17 import org.apache.tapestry5.ioc.OperationTracker;
18 import org.apache.tapestry5.services.LocalizationSetter;
19 import org.apache.tapestry5.services.Request;
20 import org.apache.tapestry5.services.Response;
21 import org.apache.tapestry5.services.assets.AssetRequestHandler;
22 import org.apache.tapestry5.services.assets.StreamableResource;
23 import org.apache.tapestry5.services.javascript.JavaScriptStack;
24 import org.apache.tapestry5.services.javascript.JavaScriptStackSource;
25 import org.slf4j.Logger;
26
27 import java.io.IOException;
28 import java.util.regex.Matcher;
29 import java.util.regex.Pattern;
30
31 public class StackAssetRequestHandler implements AssetRequestHandler
32 {
33 private final Logger logger;
34
35 private final LocalizationSetter localizationSetter;
36
37 private final ResourceStreamer resourceStreamer;
38
39
40
41
42 private final Pattern pathPattern = Pattern.compile("^(.+)/(.+)/(.+)\\.js$");
43
44 private final OperationTracker tracker;
45
46 private final JavaScriptStackAssembler javaScriptStackAssembler;
47
48 private final JavaScriptStackSource stackSource;
49
50 public StackAssetRequestHandler(Logger logger, LocalizationSetter localizationSetter,
51 ResourceStreamer resourceStreamer,
52 OperationTracker tracker,
53 JavaScriptStackAssembler javaScriptStackAssembler,
54 JavaScriptStackSource stackSource)
55 {
56 this.logger = logger;
57 this.localizationSetter = localizationSetter;
58 this.resourceStreamer = resourceStreamer;
59 this.tracker = tracker;
60 this.javaScriptStackAssembler = javaScriptStackAssembler;
61 this.stackSource = stackSource;
62 }
63
64 public boolean handleAssetRequest(Request request, Response response, final String extraPath) throws IOException
65 {
66 return tracker.perform(String.format("Streaming JavaScript asset stack %s", extraPath),
67 new IOOperation<Boolean>()
68 {
69 public Boolean perform() throws IOException
70 {
71 return streamStackResource(extraPath);
72 }
73 });
74 }
75
76 private boolean streamStackResource(String extraPath) throws IOException
77 {
78 Matcher matcher = pathPattern.matcher(extraPath);
79
80 if (!matcher.matches())
81 {
82 logger.warn(String.format("Unable to parse '%s' as an asset stack path", extraPath));
83
84 return false;
85 }
86
87 String checksum = matcher.group(1);
88 String localeName = matcher.group(2);
89 final String stackName = matcher.group(3);
90
91 final boolean compressed = checksum.startsWith("z");
92
93 if (compressed)
94 {
95 checksum = checksum.substring(1);
96 }
97
98 final JavaScriptStack stack = stackSource.findStack(stackName);
99
100 if (stack == null)
101 {
102 logger.warn(String.format("JavaScript stack '%s' not found.", stackName));
103 return false;
104 }
105
106
107
108
109
110 localizationSetter.setNonPersistentLocaleFromLocaleName(localeName);
111
112 StreamableResource resource =
113 tracker.perform(String.format("Assembling JavaScript asset stack '%s' (%s)",
114 stackName, localeName),
115 new IOOperation<StreamableResource>()
116 {
117 public StreamableResource perform() throws IOException
118 {
119
120 return javaScriptStackAssembler.assembleJavaScriptResourceForStack(stackName, compressed,
121 stack.getJavaScriptAggregationStrategy());
122
123 }
124 });
125
126
127 if (resource == null)
128 {
129 return false;
130 }
131
132 return resourceStreamer.streamResource(resource, checksum, ResourceStreamer.DEFAULT_OPTIONS);
133 }
134 }